
import { ERR_SWITCH_STATE } from "../../../extention/return_code";
import { jobGoto } from "../../../job/goto";
import { jobSpread } from "../../../job/spread";
import { jobTransfer } from "../../../job/transfer";
import { jobWithdraw } from "../../../job/withdraw";
import { getApproprateEnergy, getMinEnergy, spawnCreep } from "../../../role/spawn";
import { getActualResourceAmount, getCapacity, getFreeCapacity, getResourceAmount } from "../../../util/store";
import { GroupWork } from "./work";

export class GroupCarriers extends GroupWork{
    serialize(){
        return {super:super.serialize()};
    }
    deserialize(obj){
        super.deserialize(obj.super);
        return this;
    }
    spawn(){
        const creep=spawnCreep(this.spawnRoom, {
            require: [MOVE,CARRY,MOVE,MOVE,CARRY,CARRY],
            move:.50,
            carry:.50,
        },{
            memory:{
                role:'carrier',
            }
        }, this.size === 0?getMinEnergy(this.spawnRoom):getApproprateEnergy(this.spawnRoom));
        if(creep instanceof Creep){
            this.addCreep(creep);
            return OK;
        }
        return creep;
    }
    /**
     * 
     * @param {Array<Structure | Creep} withdrawTargets 
     * @returns {CreepActionReturnCode}
     */
    run(withdrawTargets=undefined){
        if(withdrawTargets===undefined){
            withdrawTargets=jobWithdraw.getTargets(this.spawnRoom);
        }
        const transferTargets = jobTransfer
            .getTargets(this.spawnRoom)
            .filter((target)=>getFreeCapacity(target) > 0);
        const creeps = [];
        for(let creep of this.creeps){
            if(creep.spawning){
                continue;
            }
            if(!Boolean(jobGoto.getTarget(creep))){
                creeps.push(creep);
                continue;
            }

            try{
                this.creepRun(creep, withdrawTargets, transferTargets);
            }catch(e){
                console.log('Error(from '+creep.name+'):'+e.message+'\n'+e.stack);
            }
        }

        for(let creep of creeps){
            try{
                this.creepRun(creep, withdrawTargets, transferTargets);
            }catch(e){
                console.log('Error(from '+creep.name+'):'+e.message+'\n'+e.stack);
            }
        }
        return OK;
    }

    /**
     * 
     * @param {AnyCreep} creep 
     * @param {Array<AnyCreep|AnyStructure} _withdrawTargets 
     * @param {Array<AnyCreep|AnyStoreStructure} transferTargets 
     * @returns {import("../../../extention/return_code").GroupActionReturnCode}
     */
    creepWork(creep, _withdrawTargets=undefined, transferTargets = undefined){
        let ret;

        transferTargets = transferTargets.filter((target)=>getFreeCapacity(target) > 0);

        if(transferTargets.length === 0){
            return ERR_SWITCH_STATE;
        }

        const ind = jobGoto.getClosestIndex(creep, transferTargets);
        const tmp = transferTargets[0];
        transferTargets[0] = transferTargets[ind];
        transferTargets[ind] = tmp;
        
        // creep.moveTo(transferTargets[0], {visualizePathStyle:{stroke: '#'}})

        ret = jobTransfer.run(creep, undefined, transferTargets, true);

        if(getActualResourceAmount(creep)/getCapacity(creep) <= 0.15){
            return ERR_SWITCH_STATE;
        }
        return ret;
    }
    creepGet(creep, withdrawTargets=undefined, transferTargets = undefined){
        let ret;

        withdrawTargets = withdrawTargets.filter((target)=>getResourceAmount(target) >= 15);
        if(withdrawTargets.length === 0){
            return ERR_SWITCH_STATE;
        }

        ret=jobWithdraw.run(creep, withdrawTargets);
        creep.say("get:"+ret);
        if(ret===ERR_NOT_FOUND){
            jobSpread.run(creep);
        }
        const isFull = (getActualResourceAmount(creep)/getCapacity(creep))>=(transferTargets.length>0 ? .65 : 1.00);
        // const noTarget =  !withdrawTargets.some((target)=>getActualResourceAmount(target)>0);
        const noTarget =  withdrawTargets.length === 0;
        const haveEnergy = getActualResourceAmount(creep) > 0;
        if(isFull || (noTarget && haveEnergy)){
            return ERR_SWITCH_STATE;
        }
        return ret;
    }
}